#ifndef __SHIP_TEMPLATE_HEADER
#define __SHIP_TEMPLATE_HEADER

#include "ship_types.h"
#include <string>
#include <vector>
#include <array>

class SlotTemplate;
namespace Json { class Value; }

class ShipTemplate {
	public:
		// Creates a Template from Json
		ShipTemplate( const Json::Value & _ship, std::string name = "" );

		// Creates a Template copying specified values
		ShipTemplate( int _shipClass, int _maxHp, int _controlTowers,
					  const std::array<std::vector<SlotTemplate>,ALL_SIDES> & _sides, std::string name = "" );

		// Copy Constructor
		ShipTemplate( const ShipTemplate & _ship );

		bool operator== (const ShipTemplate & other) const;

		// Saves the Template to Json
		Json::Value convertToJson() const;

		// ALL FUNCTIONS HERE SIMPLY CREATE AN APPROPRIATE COPY OF THE TEMPLATE

		// Adds a slot to one side
		ShipTemplate addSlotTemplate( int _side, const SlotTemplate & _slot ) const;

		// Adds symmetric slots to horizontally opposite sides
		ShipTemplate addSymmetricSlotTemplate( int _side, SlotTemplate _slot ) const;

		// Removes a slot from one side
		ShipTemplate rmSlotTemplate( int _side, int _slot ) const;

		// Removes slots to horizontally opposite sides
		ShipTemplate rmSymmetricSlotTemplate( int _side, int _slot ) const;

		// Toggles the allowedCannons property of a Slot
		ShipTemplate toggleSlotTemplate( int _side, int _slot ) const;

		// Toggles the allowedCannons property of horizontally opposite Slots
		ShipTemplate toggleSymmetricSlotTemplate( int _side, int _slot ) const;


		// Sets the max hp of the ShipTemplate
		ShipTemplate setMaxHp( int _hp ) const;

		// Sets the number of towers of the ShipTemplate
		ShipTemplate setTowers( int _towers ) const ;

		// SUMMARIES ------------------

		// Side, Dirs[], Cannons?, Cost
		std::vector<std::array<std::string,4>> getSlotTemplateSummaries() const;
		// Name, Class, Cost
		std::array<std::string,3> getSummary() const;

		// GETTERS --------------------

		int getSlotTemplatesNumber() const;
		int getSlotTemplatesNumber(int _side) const;
		int getCost() const;
		int getShipTemplateClass() const;
		int getMaxHp() const;
		int getTowers() const;
		std::vector<SlotTemplate> getSide(int i) const;
		const SlotTemplate & getSlotTemplate(int i, int j) const;

		// The Template's name
		std::string name;
	private:
		// GENERAL VARIABLES
		const int shipClass;

		// STRUCTURAL VARIABLES
		const int maxHp;
		const std::array<std::vector<SlotTemplate>,ALL_SIDES> sides;
		const int controlTowers; // Number of control towers

		// ECONOMICS VARIABLES
		// The cost NEEDS to be the last declared member of the Template, so that it is
		// built last and it can look all other members
		const int cost; // LEAVE AS LAST MEMBER!

		// STATIC METHODS TO CREATE INSTANCES
		static int computeCost( const ShipTemplate * _shipTemplate );
		static std::array<std::vector<SlotTemplate>,ALL_SIDES> computeSides(const Json::Value & _sides);
};

#endif
